package cn.echoparrot.domain.entity;

import com.fasterxml.jackson.annotation.JsonProperty;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.PositiveOrZero;
import lombok.*;
import lombok.experimental.Accessors;
import org.springframework.data.annotation.Id;
import org.springframework.data.neo4j.core.schema.GeneratedValue;
import org.springframework.data.neo4j.core.schema.Node;
import org.springframework.data.neo4j.core.schema.Property;
import java.time.LocalDateTime;

/**
 * 知识库（也叫资料库）
 * Dataset是一个聚合根实体(root entity, DDD术语）。知识库里有文件，文件切分成多个片段。
 * 知识库名称在业务过程中应当是可以修改的。但从数据库出来后的使用过程中，应当是只读的。
 * 那数据库应当如何追踪一个知识库？应当是有一个ID表达的。豆包与Dify的Dataset.id都是String。
 * 如果只是在数据库实例里作为唯一键，int型是否更合适？neo4j有一个内部ID id(node) 非负整数。
 * neo4j的id(node)只在运行期间是确定的，默认有可能是优先使用最小的ID。随着实体删除或数据迁移，id(node)可能会被重新分配。
 *
 * 如果是没有业务意义的ID，只起到全局追踪作用，那elementId(node)是一个更好的选择。
 * 如果是为了兼容其它数据库实现，那String 类型的UUID是更好的选择。neo4j 支持apoc.create.uuid()
 * 真正具有业务意义的ID，其实是知识库的名称。这个知识库的名称是在一定范围内要求唯一的、不重名的。
 *
 * Label会参与组成neo4j数据库的constraint名，index是建立在指定Label的节点的属性上。
 * 由于dataset被设计成独立的逻辑隔离的。需要对每一个dataset创建一个独立的constraint和index。
 *
 * Spring Data Neo4j在实例化@NodeEntity注解的类时，不需要必须有无参构造方法，但必须满足：
 * 有无参构造方法，或者
 * 只有一个有参构造方法
 * 如果类中定义了多个有参构造方法且没有无参构造方法，Spring Data Neo4j会报错。
 */
@Node("Dataset")
@Accessors(fluent = true, chain = true)
@Data
@ToString
@EqualsAndHashCode
public class Dataset {
    @Id
    @GeneratedValue
    @JsonProperty
    private Long id;

    @Property("name")
    @JsonProperty
    private  String name;

    @Property("description")
    @JsonProperty
    private  String description;

    @NotBlank
    @Property("embeddingModel")
    @JsonProperty
    private  String embeddingModel;

    @PositiveOrZero
    @Property("userId")
    @JsonProperty
    private  Integer userId;

    @Property("createdAt")
    @JsonProperty
    private  LocalDateTime createdAt;

    @PositiveOrZero
    @Property
    @JsonProperty
    private int fileCount;

    public Dataset(){
    }


    public String labelName4Segment() {
        String hex = String.valueOf(id);
        return "Segment_"+id;
    }
    public String indexName() {
        return "vector_idx_" + labelName4Segment();
    }

}

